{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Day12 正则常用“非获取匹配”一网打尽"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　通过**【Day11】**的内容，我们认识到了**正则表达式**中“非获取匹配”的含义，而今天的内容就将建立在昨天内容之上，为大家介绍**正则表达式**中常见的4种不同功能的“非获取匹配”语法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **?=正向肯定预查**\n",
    "\n",
    "　　首先我们来学习第一种“非获取匹配”语法——**正向肯定预查**，与其说是学习，不如称之为回顾，因为在**【Day11】**内容最后我们就对其进行了介绍，按照`模式1(?=模式2)`的格式，其意义为以“非获取匹配”的方式对后面紧紧衔接`模式2`的`模式1`进行匹配："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-09-08T11:25:28.390930Z",
     "iopub.status.busy": "2020-09-08T11:25:28.389933Z",
     "iopub.status.idle": "2020-09-08T11:25:28.402898Z",
     "shell.execute_reply": "2020-09-08T11:25:28.401901Z",
     "shell.execute_reply.started": "2020-09-08T11:25:28.390930Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['AA', 'AA']"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "# 匹配所有 两个大写字母一个数字_ 中的“两个大写字母”\n",
    "s = '_AA2_AA2_AA2_AA2_BB3|'\n",
    "\n",
    "# 想当然的写法，由于前面的匹配过程中_被消耗，导致之后的匹配失败\n",
    "re.findall('_([A-Z]{2})\\d{1}_', s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-09-08T11:25:28.403897Z",
     "iopub.status.busy": "2020-09-08T11:25:28.403897Z",
     "iopub.status.idle": "2020-09-08T11:25:28.414867Z",
     "shell.execute_reply": "2020-09-08T11:25:28.413869Z",
     "shell.execute_reply.started": "2020-09-08T11:25:28.403897Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['AA', 'AA', 'AA', 'AA']"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 改用正向肯定预查\n",
    "re.findall('([A-Z]{2})(?=\\d{1}_)', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **?!正向否定预查**\n",
    "\n",
    "　　接下来我们来学习第二种“非获取匹配”语法——**正向否定预查**，它与**正向肯定预查**功能相反，按照`模式1(?!模式2)`的格式，其意义为以“非获取匹配”的方式对后面不衔接`模式2`的`模式1`进行匹配："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-09-08T11:25:28.416860Z",
     "iopub.status.busy": "2020-09-08T11:25:28.416860Z",
     "iopub.status.idle": "2020-09-08T11:25:28.426834Z",
     "shell.execute_reply": "2020-09-08T11:25:28.425837Z",
     "shell.execute_reply.started": "2020-09-08T11:25:28.416860Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['AA', 'AA', 'AA', 'AA']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "# 匹配所有 两个大写字母一个数字且之后不衔接| 中的“两个大写字母”\n",
    "s = '_AA2_AA2_AA2_AA2_BB3|'\n",
    "\n",
    "# 配合正向否定预查\n",
    "re.findall('([A-Z]{2})\\d{1}(?!\\|)', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **?<=反向肯定预查**\n",
    "\n",
    "　　接下来我们来学习第三种“非获取匹配”语法——**反向肯定预查**，它按照`(?<=模式1)模式2`的格式，其意义为以“非获取匹配”的方式对前面为`模式1`的`模式2`进行匹配："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-09-08T11:25:28.427832Z",
     "iopub.status.busy": "2020-09-08T11:25:28.427832Z",
     "iopub.status.idle": "2020-09-08T11:25:28.444788Z",
     "shell.execute_reply": "2020-09-08T11:25:28.443790Z",
     "shell.execute_reply.started": "2020-09-08T11:25:28.427832Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['AA', 'AA', 'AA', 'AA']"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "# 匹配所有 _两个大写字母一个数字_ 中的“两个大写字母”\n",
    "s = '_AA2_AA2_AA2_AA2_BB3|'\n",
    "\n",
    "# 配合反向否定预查和正向肯定预查\n",
    "re.findall('(?<=_)([A-Z]{2})\\d{1}(?=_)', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **?<!反向否定预查**\n",
    "\n",
    "　　接下来我们来学习第四种“非获取匹配”语法——**反向否定预查**，它按照`(?<!模式1)模式2`的格式，其意义为以“非获取匹配”的方式对前面不为`模式1`的`模式2`进行匹配："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-09-08T11:25:28.446782Z",
     "iopub.status.busy": "2020-09-08T11:25:28.446782Z",
     "iopub.status.idle": "2020-09-08T11:25:28.459749Z",
     "shell.execute_reply": "2020-09-08T11:25:28.458749Z",
     "shell.execute_reply.started": "2020-09-08T11:25:28.446782Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['AA', 'AA', 'AA', 'AA']"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "# 匹配所有 非_两个大写字母一个数字 中的“两个大写字母”\n",
    "s = '|AA2|AA2|AA2|AA2_BB3_'\n",
    "\n",
    "# 配合反向否定预查\n",
    "re.findall('(?<!_)([A-Z]{2})\\d{1}', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Day12 课后小测验\n",
    "\n",
    "　　趁热打铁，请你观察下面的字符串，然后提取出符合`XXX(v或a) 的 XX(n) XX(n) ... XX(n)`的内容，即从动词或形容词开始，经过衔接`的`以及之后连续的名词内容，且开头的动词或形容词前的代号必须为11，譬如下面的`target`中`严重(a) 的 军事(n) 挑衅(n) 行为(n)`就满足要求，而`交涉(v) 的 中国边防部队(n) 巡逻(n) 人员(n)`不满足要求（请你必须使用到今天所教的“非获取匹配”中的至少一种方法）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-09-08T11:25:28.460783Z",
     "iopub.status.busy": "2020-09-08T11:25:28.460783Z",
     "iopub.status.idle": "2020-09-08T11:25:28.469720Z",
     "shell.execute_reply": "2020-09-08T11:25:28.468724Z",
     "shell.execute_reply.started": "2020-09-08T11:25:28.460783Z"
    }
   },
   "outputs": [],
   "source": [
    "target = '''11严重(a) 的 军事(n) 挑衅(n) 行为(n) 令人发指(i)  行为(n) 00交涉(v) 的 中国边防部队(n) 巡逻(n) 人员(n) 鸣枪(v) 威胁(v) '''"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:55:19.898241Z",
     "iopub.status.busy": "2020-08-26T12:55:19.897245Z",
     "iopub.status.idle": "2020-08-26T12:55:19.904225Z",
     "shell.execute_reply": "2020-08-26T12:55:19.903227Z",
     "shell.execute_reply.started": "2020-08-26T12:55:19.898241Z"
    }
   },
   "source": [
    "　　请将你的答案截图发到本帖评论区~"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['严重(a) 的 军事(n) 挑衅(n) 行为(n)']"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "re.findall('(?<=11)([\\u4e00-\\u9fa5]+\\([va]\\) 的 .*?)[ \\u4e00-\\u9fa5]+\\([^n]\\)', target)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
